CloudFormationでgp3のRDS DBインスタンスを作成してみた
CloudFormationでもgp3を指定できるのかな
こんにちは、のんピ(@non____97)です。
先日、RDSがgp3をサポートしましたね。
私は基本的に構築はAWS CDKで行うので、CloudFormationもgp3をサポートしているのか非常に気になりました。
AWS::RDS::DBInstance
を確認してみると、以下のようにストレージタイプはstandard
とgp2
、io1
のみで、gp3はサポートしていないようです。
StorageType
Specifies the storage type to be associated with the DB instance.
Valid values: standard | gp2 | io1
The standard value is also known as magnetic.
If you specify io1, you must also include a value for the Iops parameter.
Default: io1 if the Iops parameter is specified, otherwise gp2
For more information, see Amazon RDS DB Instance Storage in the Amazon RDS User Guide.
Amazon Aurora
Not applicable. Aurora data is stored in the cluster volume, which is a single, virtual volume that uses solid state drives (SSDs).
Required: No
Type: String
Update requires: Some interruptions
これは悲しいですね。
ただ、どうしても私は諦めきれませんでした。
そんな私の足掻きをご覧ください。
いきなりまとめ
- ドキュメントには記載されていないが、CloudFormationでgp3のRDS DBインスタンスを作成できる
- (少なくともRDSの)CloudFormationのコードはJavaで書かれている
CloudFormationのソースコードを眺めてみる
サポートされる/されないは別として、ドキュメントに書かれていなくても実は動かせるなんてことはよくある話です。
どうしてもCloudFormationで設定したかったので、GitHubでRDS DBインスタンスのソースコードを見てみます。
すると、[DBInstance] Add GP3 StorageThroughput Attribute #353
というPRを見つけました。
このPRでStorageThroughput
をパラメーターとして受け付けるようになったようです。
さらに、このPRの変更履歴を見てみると、以下のようにAWS SDKのバージョンを2.17.267
から2.18.11
に変更していました。
<dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>rds</artifactId> - <version>2.17.267</version> + <version>2.18.11</version> </dependency> <dependency> <groupId>software.amazon.awssdk</groupId>
他のソースコードを見る限りCloudFormationはJavaで書かれているようです。AWS SDK for JavaのAPI Referenceを確認してみましょう。
AWS SDK for Javaのバージョンが2.18.14
にはなりますが、確かにstorageType()
は受け取る値としてgp3
をサポートしていますね。
storageType
public final String storageType() Specifies the storage type to be associated with the DB instance.
Valid values: gp2 | gp3 | io1 | standard
If you specify io1 or gp3, you must also include a value for the Iops parameter.
Default: io1 if the Iops parameter is specified, otherwise gp2
加えて、CloudFormationのJavaのソースコードを読んでも「standard
とgp2
、io1
以外のストレージタイプは拒否する」といった処理はしていないようでした。
なんだかgp3を指定できる気がしてきました。
やってみた
それではRDSのストレージタイプにgp3を指定してみましょう。
今回はCloudFormationではなく、AWS CDKで定義します。
2022/11/10現在のAWS CDKの最新バージョンである2.50.0
のストレージタイプのenumであるStorageTypeはgp3をサポートしていませんでした。そのため、escape hatchesで指定します。
2022/12/8 追記ここから
AWS CDK v2.54.0からAWS CDKでもRDS DBインスタンスのストレージタイプにgp3を指定できるようになりました。
2022/12/8 追記ここまで
import * as cdk from "aws-cdk-lib"; import { Construct } from "constructs"; export class RdsStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); // VPC const vpc = new cdk.aws_ec2.Vpc(this, "VPC", { ipAddresses: cdk.aws_ec2.IpAddresses.cidr("10.0.1.0/24"), enableDnsHostnames: true, enableDnsSupport: true, natGateways: 0, maxAzs: 2, subnetConfiguration: [ { name: "Public", subnetType: cdk.aws_ec2.SubnetType.PUBLIC, cidrMask: 26, }, { name: "Isolated", subnetType: cdk.aws_ec2.SubnetType.PRIVATE_ISOLATED, cidrMask: 26, }, ], }); // RDS Subnet Group const subnetGroup = new cdk.aws_rds.SubnetGroup(this, "RDS Subnet Group", { vpc, description: "RDS Subnet Group", subnetGroupName: "rds-subgrp", vpcSubnets: { subnetType: cdk.aws_ec2.SubnetType.PRIVATE_ISOLATED, }, }); // RDS DB Instance const dbInstance = new cdk.aws_rds.DatabaseInstance( this, "RDS DB Instance", { engine: cdk.aws_rds.DatabaseInstanceEngine.postgres({ version: cdk.aws_rds.PostgresEngineVersion.VER_14_4, }), vpc, allocatedStorage: 20, availabilityZone: vpc.availabilityZones[0], backupRetention: cdk.Duration.days(0), instanceIdentifier: "rds-db-instance", instanceType: cdk.aws_ec2.InstanceType.of( cdk.aws_ec2.InstanceClass.T3, cdk.aws_ec2.InstanceSize.MICRO ), multiAz: false, port: 5432, publiclyAccessible: false, storageEncrypted: true, storageType: cdk.aws_rds.StorageType.GP2, subnetGroup, } ); // Set DB Instance storage type to gp3 const cfnDbInstance = dbInstance.node .defaultChild as cdk.aws_rds.CfnDBInstance; cfnDbInstance.addPropertyOverride("StorageType", "gp3"); } }
こちらのコードでデプロイすると、確かにストレージタイプがgp3になっており、IOPS、スループットも表示されていました。
AWS CLIでRDS DBインスタンスの設定を確認すると以下のようになります。
$ aws rds describe-db-instances { "DBInstances": [ { "DBInstanceIdentifier": "rds-db-instance", "DBInstanceClass": "db.t3.micro", "Engine": "postgres", "DBInstanceStatus": "available", "MasterUsername": "postgres", "Endpoint": { "Address": "rds-db-instance.cicjym7lykmq.us-east-1.rds.amazonaws.com", "Port": 5432, "HostedZoneId": "Z2R2ITUGPM61AM" }, "AllocatedStorage": 20, "InstanceCreateTime": "2022-11-10T11:53:47.878000+00:00", "PreferredBackupWindow": "07:00-07:30", "BackupRetentionPeriod": 0, "DBSecurityGroups": [], "VpcSecurityGroups": [ { "VpcSecurityGroupId": "sg-0a5833c43b7305a67", "Status": "active" } ], "DBParameterGroups": [ { "DBParameterGroupName": "default.postgres14", "ParameterApplyStatus": "in-sync" } ], "AvailabilityZone": "us-east-1a", "DBSubnetGroup": { "DBSubnetGroupName": "rds-subgrp", "DBSubnetGroupDescription": "RDS Subnet Group", "VpcId": "vpc-0b760a6bfa7ddfbf4", "SubnetGroupStatus": "Complete", "Subnets": [ { "SubnetIdentifier": "subnet-07246e0e3e1c6a1dc", "SubnetAvailabilityZone": { "Name": "us-east-1b" }, "SubnetOutpost": {}, "SubnetStatus": "Active" }, { "SubnetIdentifier": "subnet-091b4b6aae89acbe2", "SubnetAvailabilityZone": { "Name": "us-east-1a" }, "SubnetOutpost": {}, "SubnetStatus": "Active" } ] }, "PreferredMaintenanceWindow": "thu:08:47-thu:09:17", "PendingModifiedValues": {}, "MultiAZ": false, "EngineVersion": "14.4", "AutoMinorVersionUpgrade": true, "ReadReplicaDBInstanceIdentifiers": [], "LicenseModel": "postgresql-license", "Iops": 3000, "OptionGroupMemberships": [ { "OptionGroupName": "default:postgres-14", "Status": "in-sync" } ], "PubliclyAccessible": false, "StorageType": "gp3", "DbInstancePort": 0, "StorageEncrypted": true, "KmsKeyId": "arn:aws:kms:us-east-1:<AWSアカウントID>:key/4544a543-32d6-4103-a1df-313116669a3e", "DbiResourceId": "db-WEKRXTLQALPG5SHWDSS2PYMZZA", "CACertificateIdentifier": "rds-ca-2019", "DomainMemberships": [], "CopyTagsToSnapshot": true, "MonitoringInterval": 0, "DBInstanceArn": "arn:aws:rds:us-east-1:<AWSアカウントID>:db:rds-db-instance", "IAMDatabaseAuthenticationEnabled": false, "PerformanceInsightsEnabled": false, "DeletionProtection": false, "AssociatedRoles": [], "TagList": [ { "Key": "aws:cloudformation:stack-id", "Value": "arn:aws:cloudformation:us-east-1:<AWSアカウントID>:stack/RdsStack/a1d78750-5c27-11ed-a166-126e4ccc5485" }, { "Key": "aws:cloudformation:stack-name", "Value": "RdsStack" }, { "Key": "aws:cloudformation:logical-id", "Value": "RDSDBInstance1137C508" } ], "CustomerOwnedIpEnabled": false, "ActivityStreamStatus": "stopped", "BackupTarget": "region", "NetworkType": "IPV4", "StorageThroughput": 125 } ] }
スループットとIOPSを変更してみる
せっかくgp3なので、スループットとIOPSをベースラインのものから変更してみましょう。
RDSのgp3はストレージサイズが400 GiB以上からスループットとIOPSを変更できるようになります。今回は以下のように設定を変更します。
- ストレージサイズ : 20 GiB -> 400 GiB
- スループット : 125 MiBps -> 600 MiBps
- IOPS : 3000 IOPS -> 15,000 IOPS
AWS CDKのコードは以下の通りです。
import * as cdk from "aws-cdk-lib"; import { Construct } from "constructs"; export class RdsStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); // VPC const vpc = new cdk.aws_ec2.Vpc(this, "VPC", { ipAddresses: cdk.aws_ec2.IpAddresses.cidr("10.0.1.0/24"), enableDnsHostnames: true, enableDnsSupport: true, natGateways: 0, maxAzs: 2, subnetConfiguration: [ { name: "Public", subnetType: cdk.aws_ec2.SubnetType.PUBLIC, cidrMask: 26, }, { name: "Isolated", subnetType: cdk.aws_ec2.SubnetType.PRIVATE_ISOLATED, cidrMask: 26, }, ], }); // RDS Subnet Group const subnetGroup = new cdk.aws_rds.SubnetGroup(this, "RDS Subnet Group", { vpc, description: "RDS Subnet Group", subnetGroupName: "rds-subgrp", vpcSubnets: { subnetType: cdk.aws_ec2.SubnetType.PRIVATE_ISOLATED, }, }); // RDS DB Instance const dbInstance = new cdk.aws_rds.DatabaseInstance( this, "RDS DB Instance", { engine: cdk.aws_rds.DatabaseInstanceEngine.postgres({ version: cdk.aws_rds.PostgresEngineVersion.VER_14_4, }), vpc, allocatedStorage: 400, availabilityZone: vpc.availabilityZones[0], backupRetention: cdk.Duration.days(0), instanceIdentifier: "rds-db-instance", instanceType: cdk.aws_ec2.InstanceType.of( cdk.aws_ec2.InstanceClass.T3, cdk.aws_ec2.InstanceSize.MICRO ), multiAz: false, port: 5432, publiclyAccessible: false, storageEncrypted: true, storageType: cdk.aws_rds.StorageType.GP2, subnetGroup, } ); // Set DB Instance storage type to gp3 const cfnDbInstance = dbInstance.node .defaultChild as cdk.aws_rds.CfnDBInstance; cfnDbInstance.addPropertyOverride("StorageType", "gp3"); // Storage Throughput cfnDbInstance.addPropertyOverride("StorageThroughput", "600"); // IOPS cfnDbInstance.addPropertyOverride("Iops", "15000"); } }
npx cdk diff
で変更の差分を確認してみます。
> (master ⚡) npx cdk diff Stack RdsStack Resources [~] AWS::RDS::DBInstance RDS DB Instance RDSDBInstance1137C508 ├─ [~] AllocatedStorage │ ├─ [-] 20 │ └─ [+] 400 ├─ [+] Iops │ └─ 15000 └─ [+] StorageThroughput └─ 600
意図した通りの変更が行われそうですね。
それでは、こちらのコードでデプロイします。
デプロイ後、RDSのコンソールを確認すると、IOPSとスループットが指定したものに変更されていました。
AWS CLIでRDS DBインスタンスの設定を確認すると以下のようになります。
$ aws rds describe-db-instances { "DBInstances": [ { "DBInstanceIdentifier": "rds-db-instance", "DBInstanceClass": "db.t3.micro", "Engine": "postgres", "DBInstanceStatus": "available", "MasterUsername": "postgres", "Endpoint": { "Address": "rds-db-instance.cicjym7lykmq.us-east-1.rds.amazonaws.com", "Port": 5432, "HostedZoneId": "Z2R2ITUGPM61AM" }, "AllocatedStorage": 400, "InstanceCreateTime": "2022-11-10T11:53:47.878000+00:00", "PreferredBackupWindow": "07:00-07:30", "BackupRetentionPeriod": 0, "DBSecurityGroups": [], "VpcSecurityGroups": [ { "VpcSecurityGroupId": "sg-0a5833c43b7305a67", "Status": "active" } ], "DBParameterGroups": [ { "DBParameterGroupName": "default.postgres14", "ParameterApplyStatus": "in-sync" } ], "AvailabilityZone": "us-east-1a", "DBSubnetGroup": { "DBSubnetGroupName": "rds-subgrp", "DBSubnetGroupDescription": "RDS Subnet Group", "VpcId": "vpc-0b760a6bfa7ddfbf4", "SubnetGroupStatus": "Complete", "Subnets": [ { "SubnetIdentifier": "subnet-07246e0e3e1c6a1dc", "SubnetAvailabilityZone": { "Name": "us-east-1b" }, "SubnetOutpost": {}, "SubnetStatus": "Active" }, { "SubnetIdentifier": "subnet-091b4b6aae89acbe2", "SubnetAvailabilityZone": { "Name": "us-east-1a" }, "SubnetOutpost": {}, "SubnetStatus": "Active" } ] }, "PreferredMaintenanceWindow": "thu:08:47-thu:09:17", "PendingModifiedValues": {}, "MultiAZ": false, "EngineVersion": "14.4", "AutoMinorVersionUpgrade": true, "ReadReplicaDBInstanceIdentifiers": [], "LicenseModel": "postgresql-license", "Iops": 15000, "OptionGroupMemberships": [ { "OptionGroupName": "default:postgres-14", "Status": "in-sync" } ], "PubliclyAccessible": false, "StorageType": "gp3", "DbInstancePort": 0, "StorageEncrypted": true, "KmsKeyId": "arn:aws:kms:us-east-1:<AWSアカウントID>:key/4544a543-32d6-4103-a1df-313116669a3e", "DbiResourceId": "db-WEKRXTLQALPG5SHWDSS2PYMZZA", "CACertificateIdentifier": "rds-ca-2019", "DomainMemberships": [], "CopyTagsToSnapshot": true, "MonitoringInterval": 0, "DBInstanceArn": "arn:aws:rds:us-east-1:<AWSアカウントID>:db:rds-db-instance", "IAMDatabaseAuthenticationEnabled": false, "PerformanceInsightsEnabled": false, "DeletionProtection": false, "AssociatedRoles": [], "TagList": [ { "Key": "aws:cloudformation:stack-id", "Value": "arn:aws:cloudformation:us-east-1:<AWSアカウントID>:stack/RdsStack/a1d78750-5c27-11ed-a166-126e4ccc5485" }, { "Key": "aws:cloudformation:stack-name", "Value": "RdsStack" }, { "Key": "aws:cloudformation:logical-id", "Value": "RDSDBInstance1137C508" } ], "CustomerOwnedIpEnabled": false, "ActivityStreamStatus": "stopped", "BackupTarget": "region", "NetworkType": "IPV4", "StorageThroughput": 600 } ] }
これが CLP やってみる
CloudFormationでRDS DBインスタンスのストレージタイプにgp3を指定できるか確認してみました。
「ドキュメントに書いてないから出来るか分からないなぁ」で悩みすぎるのではなく、勢いでトライしてみたら上手くいきました。これがCLPの「やってみる」です。(ちょっと違う気もする)
自分なりに仮説を立てて、繰り返しトライアンドエラーする重要性を改めて実感しました。
この記事が誰かの助けになれば幸いです。
以上、AWS事業本部 コンサルティング部の のんピ(@non____97)でした!